MapInfo Professioanl 产品开发代码
1 . 如何在MAPINFO PROFESSINAL 中使用自定义符号?
2 . 如何使用MAPINFO PROFESSINAL 中节点抓取、抽稀功能?
3 .如何设置、使用hotlink?
7 .MapBasic的程序在Professional下调试完成,如何移植到Runtimes上?
8 .MAPINFO PROFESSIONAL 在 VB 中 OLE Automation 二次开发介绍
9 .MAPINFO PROFESSIONAL 在 DELPHI 中 OLE Automation 二次开发介绍
10.MAPINFO PROFESSIONAL 二次开发非模态窗口的调用
MapInfo Mapx 产品开发代码
2 .自定义范围专题图
4 .在mapx中如何紧缩表
9 .在mapx中如何实现自动滚屏?
如何在MAPINFO PROFESSINAL 中使用自定义符号?
Mapinfo Professional为用户提供了丰富的区域填充图案、直(折)线类型及符号样式,为用户制作电子地图提供了极大的便利。用户不仅可以在创建空间对象时,设定对象的样式;还可以在创建对象完成之后,再改变其样式。
但由于行业的差别及其复杂性,任何制图系统都不可能提供满足所有用户需求的点、线、面样式,所以一般制图系统都为用户提供了扩展系统符号样式的机会。Mapinfo为用户提供了三种点、线、面符号编辑工具,用以扩展系统的点、线、面符号样式,以满足用户的行业需求。
一. Mapinfo Professional点符号样式
Mapinfo Professional 具有两种格式的点符号样式:位图符号及TrueType字体符号。Mapinfo Professional针对这两种符号样式,都提供了大量的可供用户直接使用的符号库。例如用户分别可以在Mapinfo Professional的Custom Symbols及有关房地产和运输业等的符号集中查看到大量的位图符号及TrueType字体符号。
1.如何自定义Mapinfo Professional位图符号
Mapinfo可以把用户自定义的BMP位图作为其点符号。具体步骤如下:
l 首先,启动一个位图处理程序,如Windows画图、Photoshop等,并在其中创建一个适当大小的位图(64×64、32×32、16×16)。应当注意的是:对于Win32位图大小不能超过128K;对Win16其大小不能超过64K。
l 将位图以256色或16色保存在Mapinfo安装目录的CustSymb目录下。
l 单击Mapinfo Professional 中的符号工具按钮,调用符号样式对话框,并单击对话框上的重置按钮,以将新建的位图符号添加到Custom Symbols符号集中。见图1。此后,用户便可以直接调用Custom Symbols 符号集中的自定义位图符号。
![]() |
图1 符号样式对话框
2.如何自定义Truetype字体符号
Mapinfo 支持许多TrueType字体,它们都带有自己的符号集。用户可以利用TrueType字体编辑程序,例如,Windows的TrueType字体造字程序或是CoreDraw 等应用程序来对Mapinfo 的TrueType字库中的TrueType 字体符号进行编辑:修改Mapinfo 自带的TrueType字体符号,或是向其中增加新的TrueType字体符号,而且用户还可以自定义TrueType字体文件,并将它们在Mapinfo中引用。
二. 利用SymbolPlotter 制作矢量点符号
SymbolPlotter是一种矢量符号编辑工具,由于它是以Mapinfo 的区域对象(Region)来表示点符号,因而利用SymbolPlotter生成的点符号能随着地图的缩放而改变其大小。 同时,利用SymbolPlotter生成Mapinfo 矢量点符号时,还可以由Mapinfo 点对象的属性值来规定矢量点符号的大小及旋转方向。见图2。
![]() |
图2 利用SymbolPlotter 制作的可变大小及具有旋转方向的矢量点符号
SymbolPlotter自带有矢量符号库,用户可以直接利用其中的矢量符号来生成Mapinfo的矢量点符号图;同时还可以对原来矢量符号库中的矢量符号重新编辑、向其中增加矢量符号,或是新建自己的矢量符号库。见图3。

图3 对SymbolPlotter自带的矢量符号可以重新编辑
但利用SymbolPlotter制作Mapinfo矢量符号与直接利用Mapinfo 符号工具在当前可编辑图层中增加点对象的区别在于:利用Mapinfo符号工具可以在当前图层的“任意”位置增加点对象,而SymbolPlotter工具只能在当前图层固定点位置增加矢量点符号。所以如果用户想生成在Mapinfo Professional环境下可缩放大小的矢量点符号图层时,则应当首先在Mapinfo Professional 环境中,利用符号工具生成一幅非矢量点符号图层,然后再利用SymbolPlotter的“Plot Symbols on Points…”命令将当前图层中的非矢量点符号对象替换成SymbolPlotter的矢量符号,以生成可随地图缩放而改变大小的矢量点符号图层。见图4。
图4 利用SymbolPlotter将非矢量符号替换为矢量符号
三. Mapinfo Professional 线符号样式
Mapinfo Professional 自带有118种线型符号,其样式都保存在Mapinfow.pen文件中。用户每次启动Mapinfo Professional 时,程序会自动调用该线符号库文件,加载其自带的线符号样式。
用户在利用Mapinfo Professional建立电子地图时,可以利用线样式工具按钮调用Mapinfo Professional 的线符号样式资源,并定义所绘线型的颜色及线宽。
![]() |
图5 在Mapinfo Professional中定义线型的样式、颜色及线宽
四. 利用Mapinfo Line Editor 2.0自定义Mapinfo线型
Mapinfo Line Editor 2.0是一个功能强大的Mapinfo线型编辑工具。利用它用户可以直接对Mapinfo的线型文件Mapinfow.pen进行编辑:更改Mapinfow.pen文件中已定义好的线型样式,或是向其中增加新的线型样式。见图6。
![]() |
图6 利用Line Editor 对Mapinfo 的已有线样式进行编辑
用户在利用Mapinfo Line Editor 2.0自定义Mapinfo 线型样式时应当注意的是:由于现在Mapinfow.pen文件最多只能保存127种线型符号,因而用户在新建一个线型文件或是直接向Mapinfow.pen文件中增加线型符号时,如果文件中的线型数量超过了127种,便应当重新建立一个线型文件,以保存更多的线型符号样式。
用户在建立了自己的线型文件后,如果想在Mapinfo Professional 中使用它,只需将其命名为Mapinfow.pen以替代Mapinfo Professional自带的线型文件,并重新启动Mapinfo Professional即可。
Mapinfow.pen 是一个与Mapinfo Professional系统相对独立的线型文件,而且用户可以跨平台使用它:例如,用户可以利用文件拷贝的方法将其由Windows98平台传送给其他Windows NT用户使用。
五. 利用Pattern Editor自定义Mapinfo区域填充样式

Pattern Editor是一个非常好用的Mapinfo 区域填充样式编辑工具。用户可以利用Pattern Editor对Mapinfo Professional自带的区域填充样式进行编辑,并保存。编辑修改后的区域填充样式可以在Mapinfo Professional 中直接使用。但目前用户还无法利用Pattern Editor来新建区域填充样式。
用户要对Mapinfo Professional 自带的区域填充样式进行修改时,只需利用鼠标点中相应的填充样式,并单击“开始编辑”按钮即可。在编辑过程中,点击鼠标右键可以向当前填充样式中增加填充“色斑”; 点击鼠标左键则减少当前填充样式中的填充“色斑”。编辑完成后,只需单击保存按钮便可将所做修改保存到Mapinfo Professional资源文件中。
用户在使用如下语句创建字体时 :
Create Text into Window Frontwindow() "Hello!" (10,10)(20,20) Font MakeFont("Helvetica", 1, 12, BLACK, WHITE)
应当注意:在创建字体的语句中采取范围优先的方式,即“Hello”后面的(x,y)指定字符串的左下及右上角位置,优先于“12”指所要创建的字体的大小。将来显示出来的字符的实际大小只由(x,y)来控制。实际上在上述的语句中指定的字体大小是无效的,但是也不能将该值设为0,否则程序运行时会出错
如果希望在创建文字时即指定文字地大小,可以使用下面的函数
CreateText( window_id , x , y , text , angle , anchor , offset ) ,此函数创建一个文本对象,该文本对象的字体大小在创建前由系统的style决定。所以在使用此函数前,设置Set Style Font MakeFont("Helv", 1, 14, BLACK,WHITE) 然后再使用此函数,可以创建指定大小的文字。
通过 hotlink 可以从地图上的对象、标注直接启动文件和 Iternet URL.过程如下:
1。首先表中应有字段,其内容为hotlink调用的文件或Iternet URL;
2。通过图层控制对话框中的热链接按钮设置热链接字段及启动热链接的方式;
3。单击主工具栏上的hotlink,当鼠标移动到相应的启动对象上时,单击启动对象即可启动链接内容;
mapbasic 语言:
[ Layer layer_id
[Activate {[Using launch_expr]|[On{[Labels]|[Objects]}|[Relative Path {
On|Off}]}]
其中的Activate 分句既是hotlink的设置语句。其中的[Using launch_expr] 指明热链接的字段或表达式,[On{[Labels]|[Objects] 指明热链接的对象,Relative Path 设置热链接的文件是相对路径或绝对路径。
语句:
Set Map Layer 1 Activate Using GEONAME On Labels Objects Relative Path On
对当前图层的热链接设置为:GEONAME 热链接字段,并且热链接对象为标注和对象本身。
如何使用MAPINFO PROFESSINAL 中节点抓取、抽稀功能?
MAPINFO PROFESSIONAL 6.5 新增加了节点抓取和抽稀的功能。节点抓取和抽稀的主要功能是,从不同对象中抓取节点集合在一起,并在保持对象的图形形状时,减少一个对象中节点的数量。
对于非常靠近的不同对象的节点,可以通过创建或编辑对象来获得,也可以通过对象之间较小的重叠和缝隙来获得。通过指定距离将节点抓取在一起,同时消除以上的重叠和缝隙。
一些对象所包含的节点可能不会对对象以及/或者应用程序产生贡献。这可能是由于数据不够多,无法记录节点位置的细微差别,或者是由于对象要解决的问题超过了应用程序所需要的。这些问题的贡献是多余的,超出了对象的显示、操作、存储。
对数据进行抽稀可以在保留对象的形状和特性的基础上,移动节点和减少对象的复杂性。
另外,这项操作可以移动在区域数据中存在的所有自相交和重叠面积。在节点抓取和抽稀之后可以移动重叠面积,也可以移动在该过程中存在的所有重叠。
对应的mapbasic 语句为
Objects Snap From tablename
[Tolerance [Node node_distance] [Vector vector_distance] [Units unit_string] ]
[Thin [Bend bend_distance] [Distance spacing_distance] [Units unit_string] ]
[Cull Area cull_area [Units unit_string] ] ]
例如对公路图层进行节点抓取,抓取的最后节点偏差为0.1 公里,内部节点偏差是0.2公里:
Objects Snap From road Tolerance Node 0.2 Vector 0.1 Units "km"
例如对区域进行节点抽稀,抽稀的三点共线距离是0.1,点与点之间的距离是0.2的语句是:
Objects Snap From Selection Thin Bend 0.1 Distance 0.2 Units "km"
移除面积小于0.2平方公里的缝隙语句是:
Objects Snap From Selection Cull Area 0.2 Units "sq km"
MapBasic动态图层技术示例程序
Mapinfo 的动态图层技术特别适用于需要显示实时数据的情况,例如:GPS监控等。下面以一个车载GPS监控为例,讲解一下Mapinfo 动态图层技术的编程。
本示例程序以文本数据文件,来模拟实时数据。
(1)首先,应当建立一个新图层,其中只放一个或几个用来“汽车”对象。
(2)每当从数据文件中读入一个新的汽车位置数据时,则重新在新位置上创建一个新的“汽车”对象,并用它来更新原来的汽车。
Fetch First From trk_xys ' Point to first record in trk_xys
Do While Not EOT(trk_xys) ' Sets up a loop that will run until
' the end of the table is reached.
x = trk_xys.x_coord ' Read the pairs of coordinates into
y = trk_xys.y_coord ' the variables
Update trucks Set Obj = CreatePoint(x,y) Where Rowid = 1
' Update the first truck
'*** The trucks table has only one records in it, so Rowid 1 is the
'*** first truck.
Fetch next from trk_xys '*** Move pointer so that the next pair of
'*** coordinates can be read from the table.
Loop
如何在MapBasic程序中提高获取点的坐标精度
在mapbaic中如果想获取地图中某个固定点的坐标,最好不要采用通过鼠标点击,然后用CommandInfo(CMD_INFO_X)和CommandInfo(CMD_INFO_Y)来获取该点的坐标。应当:先利用selector 工具选中该点,再利用CentroidX(selection.obj) , CentroidY(selection.obj),来确定该点的坐标。
现在MapBasic 能返回的坐标值的最高精度为:小数点后6位。假定一个区域其经度值在112度左右,纬度在32度左右。为了提高坐标值的精度,应作如下的处理:
dim x,y as float
x=Format$((commandinfo(cmd_info_x)-112),"##.######")+112
y=Format$((commandinfo(cmd_info_x)-32),"##.######")+32
MapBasic的程序在Professional下调试完成,如何移植到Runtimes上
利用 mapbasic 在Professional 环境下开发的应用程序,要移植到runtime 环境下运行,则应当在程序创建完软件界面后,在你的程序中再增加一条 Menu Bar Show 命令,以使你创建的软件界面上的菜单和工具条按钮能正确地显示出来。
在利用其它语言如,Visual Basic,Visual C++,Delphi等以Ole Automation方式在Mapinfo Professional 环境下开发完成的应用程序,要运行在Mapinfo Runtime 环境下,应当将创建Mapinfo 对象的语句重写,以Visual Basic 为例,在Mapinfo Professional环境下:
Dim Mapinfo as object
Set Mapinfo = Createobject("Mapinfo.Application")
在Mapinfo Runtime环境下:
Dim Mapinfo as object
Set Mapinfo = Createobject("Mapinfo.Runtime").
MAPINFO PROFESSIONAL 在 VB 中 OLE Automation 二次开发介绍
Mapinfo Professional所提供的第二种开发方式便是OLE Automation方式。使用这种开发方式可以使用户很方便地将地图化功能嵌入到已存在的应用系统内或完整地集成到商业系统中,从而创建出功能更加功能强大的应用系统。
同时,OLE Automation技术使开发者能够将MapInfo Professional集成到普通编程语言开发的应用系统中,如Visual Basic、Delphi和Visual C++等。下面结合Visual Basic 从下面几个方面进行讲解:
Ø OLE Automation 的前提 Visual Basic 工程属性的设置
由 “工程” > “工程属性” 进入工程属性对话框,并进行如下的设置。
通用:工程类型,ActiveX EXE;启动对象 Sub Main;升级ActiveX 控件。
生成:删除有关未使用的ActiveX控件的信息
部件:启动模式,独立方式。
调试:启动工程时等待创建部件。
如果用户还未在自己的工程中建立 Sub Main,则应当在模块中建立一个 Sub Main过程。
只有工程属性设置正确,才能正常调用CALLBACK。
当程序员使用VB开发Mapinfo应用时,必须将mapbasic.bas文件包含到VB工程中,路径是mapbasic的安装目录,此文件中包含mapbasic 中的常数声明。
Ø 在OLE Automation开发方式下,实现地图化的功能的步骤
使用OLE Automation 方式在VB中编程时,程序员主要是通过Mapinfo Professional对象所提供的方法及属性来实现对地图的操作的。
l VB的CreateObject 函数可以为我们创建一个Mapinfo对象,如下:
CreateObject Function Creates and returns a reference to an Automation object.
CreateObject(servername.typename [, location])
Arguments: servername
Required. The name of the application providing the object.
typename
Required.The type or class of the object to create.
location
Optional. The name of the network server where the object is to be created.
l 创建对象后,利用MI OLE自动化对象中提供的各种Method(方法)就可以调用MapBasic几乎所有的命令了。MI OLE自动化对象提供的最基本的方法包括:
Do:运行MapBasic中无返回参数的命令
Eval:运行MapBasic中有返回参数的命令
RunCommand:与Do功能相同
RunMenuCommand:运行MI的菜单命令
DataObject:返回对应窗口的IUnknown接口
l 在VB中利用Ole 自动化方式显示一幅Mapinfo地图的例子:
1. 新建一个窗口Form1,并在Form1上放置一个Picture控件Picutre1,用来显示Mapinfo地图。
2. 在VB的某个模块中定义一个全局范围的对象变量
Public mapinfo as object
3. 在某个过程(例如,整个应用程序的初始化过程,或窗体的初始化过程等)中,创建Mapinfo Application对象
Set mapinfo = CreateObject(“Mapinfo.Application”)
4. 在Form1的初始化过程中,加入如下代码。
mapinfo.do “Set Application Window ” & Form1.Picture1.hWnd
mapinfo.do “Set Next Document Parent ” & Form1.Picture1.hWnd& “ Style 1”
mapinfo.do “open table “”China”” interactive Map From China ”
Ø 如何在VB 开发过程中,直接调用Mapinfo提供的各种制图及地图操作命令。
首先在VB中设计好相应的菜单命令,或是工具条按钮(例如,地图放大)。
在VB的菜单调用过程,或是工具按钮调用过程中,加入下列代码。
Sub Mnu_Zoomin
Mapinfo.RunMenuCommand 1705 ‘地图放大
End Sub
Sub Mnu_DrawPolyline
Mapinfo.do( “run menu command 1712”) ‘画折线
End Sub
Ø 如何允许用户调整地图窗口的大小
在VB 中调整地图窗口的大小随着form 的改变而改变需要调用WINDOWS API 函数。具体使用方法如下:
1. 在模块中声明API 函数
' Windows API MoveWindow declaration
Declare Function MoveWindow Lib "User32" _
(ByVal hWnd As Long, _
ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, _ ByVal bRepaint As Long) As Long
2. 在窗口的resize事件,或者picture 的resize 事件中加入如下代码:
Private Sub Form_Resize()
Dim mHwnd As Long ' Holds the window handle
mHwnd = Val(mi.eval("WindowInfo(FrontWindow(),12)"))
' Pass the 'new' form dimensions to the MoveWindow API
MoveWindow mHwnd, 0, 0, ScaleWidth, ScaleHeight, 0
End Sub
Ø 使用OLE回调的通用过程
使用OLE回调 可以处理MI OLE自动化对象返回的消息,如:鼠标点击等。
1. 在VB的工程中加入类模块,保存为micallback.cls。并需确保工程设置正确。
2. 在工程中声明变量
Global myCallback As Object
3. 在Form1的初始化过程中加入如下代码
Set myCallback = New MICallback
mapinfo.SetCallback myCallback
'Initialize MapInfo the way we need
mapinfo.do "Create Buttonpad ""Callback"" As Toolbutton ID 2001 DrawMode 34 Cursor 138 Calling OLE ""QueryTool"""
4. 在类模块micallback中加入下列代码:
Public Sub QueryTool(ByVal CmdStr As String)
If (Left$(CmdStr, 3) ="MI:") Then
MsgBox "Unexpected callback: " & CmdStr
Exit Sub
End If
End Sub
5. 在vb中加入按钮querytool,并加入调用工具代码
mapinfo.do(“run menu command id 2001”)
6. 调用此工具,在地图上鼠标单击后会调用micallback中的QueryTool 过程。可以在QueryTool 过程中加入用户自己的代码。
Ø 退出程序时,应终此Mapinfo:
Private Sub Form_Unload(Cancel As Integer)
mapinfo.SetCallback Nothing
Set myCallback = Nothing
Set mapinfo = Nothing
End Sub
MAPINFO PROFESSIONAL 在 DELPHI 中 OLE Automation 二次开发介绍
Mapinfo Professional所提供的第二种开发方式便是OLE Automation方式。使用这种开发方式可以使用户很方便地将地图化功能嵌入到已存在的应用系统内或完整地集成到商业系统中,从而创建出功能更加功能强大的应用系统。
同时,OLE Automation技术使开发者能够将MapInfo Professional集成到普通编程语言开发的应用系统中,如Visual Basic、Delphi和Visual C++等。下面结合Delphi 5.5 从下面几个方面进行讲解:
Ø OLE Automation 的前提 引用类的添加
在delphi的工程中加入新的窗口,在窗口的引用中添加ComObj类,代码如下:
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,ComObj;
Ø 在OLE Automation开发方式下,实现地图化的功能的步骤
使用OLE Automation 方式在delphi中编程时,程序员主要是通过Mapinfo Professional对象所提供的方法及属性来实现对地图的操作的。
l Delphi的CreateObject 函数可以为我们创建一个Mapinfo对象,如下:
CreateObject Function Creates and returns a reference to an Automation object.
CreateObject(servername.typename [, location])
Arguments: servername
Required. The name of the application providing the object.
typename
Required.The type or class of the object to create.
location
Optional. The name of the network server where the object is to be created.
l 创建对象后,利用MI OLE自动化对象中提供的各种Method(方法)就可以调用MapBasic几乎所有的命令了。MI OLE自动化对象提供的最基本的方法包括:
Do:运行MapBasic中无返回参数的命令
Eval:运行MapBasic中有返回参数的命令
RunCommand:与Do功能相同
RunMenuCommand:运行MI的菜单命令
DataObject:返回对应窗口的IUnknown接口
l 在Delphi中利用Ole 自动化方式显示一幅Mapinfo地图的例子:
1. 建一个窗口Form1,并在Form1上放置一个Panel控件Panel1,用来显示Mapinfo地图。
2. Delphi 的某个模块中定义一个全局范围的对象变量
mapinfo: Variant;
3.在某个过程(例如,整个应用程序的初始化过程,或窗体的初始化过程等)中,创建Mapinfo Application对象
mapinfo := CreateOleObject('mapinfo.application');
4.在Form1的初始化过程中,加入如下代码。
mapinfo.do ('Set Next Document Parent ' + IntToStr(Panel1.Handle) + ' Style 1');
mapinfo.do('open table "d:\temp\test.tab"');
mapinfo.do('Map from test');
MapInfo.Do('set map zoom entire layer test');
Ø 如何在Delphi开发过程中,直接调用Mapinfo提供的各种制图及地图操作命令。
首先在Delphi中设计好相应的菜单命令,或是工具条按钮(例如,地图放大)。
在Delphi的菜单调用过程,或是工具按钮调用过程中,加入下列代码。
procedure TForm1.zoomin1Click(Sender: TObject);
begin
mapinfo.runmenucommand(1705);
end;
procedure TForm1.zoomout1Click(Sender: TObject);
begin
mapinfo.do (‘run menu command 1706’);
end;
Ø 如何允许用户调整地图窗口的大小
在Delphi中调整地图窗口的大小随着form 的改变而改变需要MoveWindow函数。具体使用方法如下:
在窗口的resize事件,或者picture 的resize 事件中加入如下代码:
procedure TForm1.Panel1Resize(Sender: TObject);
var
hMap: HWND;
begin
if MapInfo.eval('windowinfo(windowid(' + IntToStr(1) + '),3)') = 1 then
begin
hMap := MapInfo.eval('WindowInfo(windowid(' + IntToStr(1) + '),12)');
MoveWindow(hMap, 0, 0, Panel1.Width, Panel1.Height, true);
end;
end;
Ø 使用OLE回调的通用过程
使用OLE回调 可以处理MI OLE自动化对象返回的消息,如:鼠标点击等。
1. 在工程中新建activex automation object 类,保存为micallback
2. 在工程中声明变量
MyCallBack: TMiCallBack;
3. 在Form1的初始化过程中加入如下代码
MyCallBack := TMiCallBack.Create;
MapInfo.SetCallBack(IDispatch(MyCallBack));
MapInfo.do('Create Buttonpad "Callback" As Toolbutton ID 2001 DrawMode 32 Cursor 0 Calling OLE "MyDrawRect"');
4. 在MI_CallBack中加入MyDrawRect方法:
VIEW > type library 调出projectname.tlb 对话框,用new method 添加新的方法MyDrawRect,给方法加入参数 Cmdstr 类型BSTR;
7. 在MI_CallBack中加入下列代码:
procedure TMiCallBack.MyDrawRect(const strParam: WideString);
var
s: string;
x1, y1, x2, y2: string;
sql:string;
strtab :string;
begin
x1 := mapinfo.eval('CommandInfo(' + CMD_INFO_X + ')');
y1 := mapinfo.eval('CommandInfo(' + CMD_INFO_Y + ')');
x2 := mapinfo.eval('CommandInfo(' + CMD_INFO_X2 + ')');
y2 := mapinfo.eval('CommandInfo(' + CMD_INFO_Y2 + ')');
Form1.StatusBar1.Panels[1].Text := x1 + ', ' + y1 + ' ' + x2 + ', ' + y2;
end;
8. 在Delphi中加入按钮MyDrawRect,并加入调用工具代码
mapinfo.do (‘run menu command id 2001’);
9. 调用此工具,在地图上鼠标单击后会调用micallback中的MyDrawRect过程。可以在MyDrawRect 过程中加入用户自己的代码,以实现自己的功能。
MAPINFO PROFESSIONAL 二次开发非模态窗口的调用
MapInfo 有几个非模态的窗口,比如: 信息工具窗口、标尺窗口、信息窗口、统计窗口等。如果在二次开发中调用这些“漂浮”的窗口,需要使用mapbasic的Set Window 语句设置非模态窗口。 下面以信息工具窗口为例,讲解VB二次开发中非模态窗口的调用。
设置语句:
mapinfo.do "Set Window Info Parent " & FindZipForm.hWnd
使用信息工具即可在程序中看到信息工具窗口,当然标尺窗口。统计窗口也同理。
注意:信息工具窗口的设置与地图窗口的设置不同,当设置信息工具窗口时不需要使用Set Next Document 语句,但是设置地图窗口时需要 Set Next Document 语句的设置,这是因为应用中只有一个信息工具窗口,然而有多个地图窗口。
另外图例窗口是一个特例。通常 ,mapinfo 的用户只有一个图例窗口,然而mapbasic 语言中有Create Legend 语句,可以创建其它的图例窗口。
如果只有一个而且只能有一个图例窗口,可以使用Set Window Legend Parent 设置图例窗口。
如果创建自定义的图例窗口并且进行设置,应该使用mapbasic的Set Next Document 语句后,再使用mapbasic 的Create Legend 语句。
提示:可以在地图窗口中设置浮动的图例窗口。在 Set Next Document 语句中指明地图窗口的句柄,图例可以最为图例框漂浮在地图窗口中。
如何在MapX下读取属性值
有三种方法:
1. 由Layer对象的KeyField属性来设立要读取属性值的字段名。
接着,由Feature对象的keyValue读取此行的属性值。
2. 将图层加入到Datasets, 由Dataset对象的Value(x,y)属性,通过设置行号,列号来获得属性值。
3. 将图层加入到Datasets,之后由RowValues(ftr)获取整行的值。
Dim ds As MapXLib.Dataset, lyr As MapXLib.layer
Dim ftrs As Features
Dim ftr As Feature
Dim rv As RowValue
Dim rvs As RowValues
Dim DsName As String ‘数据集名
Dim DsRows As Long, DsCols As Long
Dim i As Long, j As Long
Set ds = Formmain.Map1.Datasets.Item(DsName)
Set lyr = ds.layer
Set ftrs = lyr.AllFeatures
DsCols = ds.Fields.Count
DsCols = DsCols + 1
DsRows = ftrs.Count
Grid1.Rows = DsRows + 1
Grid1.Cols = DsCols
Grid1.Row = 0
For i = 0 To DsCols - 1
Grid1.Col = i
Grid1.Text = ds.Fields.Item(i + 1).Name
Next i
Grid1.Col = DsCols - 1
Grid1.Text = "Fkey"
lyr.BeginAccess miAccessRead
i = 1
For Each ftr In ftrs
Set rvs = ds.RowValues(ftr)
j = 0
For Each rv In rvs
If Not IsNull(rv.Value) Then Grid1.TextArray(i * DsCols + j) = Trim(rv.Value)
j = j + 1
Next
Grid1.TextArray(i * DsCols + j) = ftr.FeatureKey
i = i + 1
Next
lyr.EndAccess miAccessEnd
Set ftr = Nothing
Set ftrs = Nothing
Set ds = Nothing
Set rv = Nothing
Set rvs = Nothing
Set lyr = Nothing
注意:BeginAccess,以及EndAccess可以明显的提高属性读取的速度。
mapx 的专题图用户可以进行完全的定制,下面是自定义范围专题图的例子。
Dim ds As New MapXLib.Dataset
Dim thm As New MapXLib.Theme
Set ds = Formmain.Map1.Datasets(ToolBars.Combo2.Text)
Set thm = ds.Themes.add(0, "aa", "aa", False)
thm.Legend.Compact = False
thm.AutoRecompute = False
'thm.ComputeTheme = False
thm.DataMax = 700
thm.DataMin = 100
thm.ThemeProperties.AllowEmptyRanges = True
thm.ThemeProperties.NumRanges = 7
thm.ThemeProperties.DistMethod = miCustomRanges
thm.ThemeProperties.RangeCategories(1).Max = 150
thm.ThemeProperties.RangeCategories(1).Min = 50
thm.ThemeProperties.RangeCategories(2).Max = 250
thm.ThemeProperties.RangeCategories(2).Min = 150
thm.ThemeProperties.RangeCategories(3).Max = 350
thm.ThemeProperties.RangeCategories(3).Min = 250
thm.ThemeProperties.RangeCategories(4).Max = 450
thm.ThemeProperties.RangeCategories(4).Min = 350
thm.ThemeProperties.RangeCategories(5).Max = 550
thm.ThemeProperties.RangeCategories(5).Min = 450
thm.ThemeProperties.RangeCategories(6).Max = 650
thm.ThemeProperties.RangeCategories(6).Min = 550
thm.ThemeProperties.RangeCategories(7).Max = 750
thm.ThemeProperties.RangeCategories(7).Min = 650
'thm.ComputeTheme = True
thm.AutoRecompute = True
thm.Visible = True
在mapx中查找对象的方法
两种方式:
1. 使用Find对象的Search方法。在mapx3.5中只能作到完全匹配查找,在MapX4.0中SearchEx方法则可以找到多个匹配的记录,其结果由 FindResult.Matches获取。详细请参看有关Find.SearchEx 方法的文档以及示例。
2. 使用Layer 对象的OBJECT.Search (strWhere)方法。其参数为SQL查询的WHERE子句。例如:
Set ftrs = lyr.Search("Character_Name = ""北京市""") ;
Set ftrs = lyrUSA.Search("TOTPOP > 1000000")
注意:1。字符串外加两个双引号。2。首先将图层加入数据集Datasets 才能使用查询。
模糊查询最方便的方法是使用第二种方法例如
Set ftrs = lyr.Search("Character_Name like ""%市""") ;模糊查询
在mapx中如何紧缩表
在Mapx4.51下可以使用LayerInfo 的创建带结构的临时表和新表的功能来完成紧缩:
Set lyr = Formmain.Map1.Layers(ToolBars.combo1.Text)
Set ds = Formmain.Map1.Datasets.add(6, lyr)
'获取被紧缩表的路径及表名
filespec = Formmain.Map1.Layers.Item(ToolBars.combo1.Text).filespec
layername = lyr.Name '将表临时存放于内存
LayerInfo.Type = 6 'miLayerInfoTypeTemp
LayerInfo.AddParameter "TableStorageType", "MemTable" '临时文件保存在磁盘上还是内存。
LayerInfo.AddParameter "Name", "lyrpack"
LayerInfo.AddParameter "Fields", ds.Fields
LayerInfo.AddParameter "Features", lyr.AllFeatures
Formmain.Map1.Layers.add LayerInfo, LayerPos
Set LayerInfo = Nothing
'从地图窗口删除原表
Formmain.Map1.Datasets.Remove (ds.Name)
Formmain.Map1.Layers.Remove (lyr.Name)
Formmain.Map1.Refresh
Set lyr = Nothing
Set ds = Nothing
Set lyr = Formmain.Map1.Layers("lyrpack")
Set ds = Formmain.Map1.Datasets.add(6, lyr)
'从磁盘删除原表
Kill filespec
在mapx中使用如何使用自定义栅格符号
使用自定义符号首先需要设定style.SymbolType 为miSymbolTypeBitmap,然后指定SymbolBitmapName 为栅格图像名即可。
下面的代码演示了如何在delphi中使用自定义的栅格符号
首先调用自定义工具画点
procedure TForm1.new1Click(Sender: TObject);
begin
map1.ControlInterface.CurrentTool :=111;
end;
在tooluses事件中如下:
procedure TForm1.Map1ToolUsed(Sender: TObject; ToolNum: Smallint; X1, Y1,
X2, Y2, Distance: Double; Shift, Ctrl: WordBool;
var EnableDefault: WordBool);
var
ssymbol :cmapxstyle;
p: CMapXPoint;
f: cmapxfeature;
begin
ssymbol:=costyle.create;
ssymbol.SymbolType :=1;
ssymbol.SymbolBitmapSize:=25;
{请注意将test.bmp文件考到mapx “共有文件路径”+“\CUSTSYMB”路径下,例如C:\Program Files\Common Files\MapInfo Shared\MapX Common 是 MapX 共有文件的缺省安装路径}
ssymbol.SymbolBitmapName:='test.BMP';
p := CoPoint.Create;
f :=cofeature.Create ;
p.Set_(x1,y1);
if toolnum=111 then begin
f:=map1.ControlInterface.FeatureFactory.CreateSymbol(p,ssymbol);
map1.ControlInterface.Layers.Item(1).AddFeature(f,EmptyParam);
end;
end;
在mapx中如何使用自定义鼠标
在mapx4.0,及以上版本中允许用户自定义鼠标。程序如下:
Map1.MousePointer = miCustomCursor
Map1.MouseIcon = "c:\windows\cursors\globe.ani"
mapx 中还对鼠标滚动轮提供支持,属性如下
Map.MouseWheelSupport=miMousewheelNoAutoScroll
在mapx 的 printmap方法:PrintMap (hDC x, y, w, h)之中,w,h,x,y的单位为himetric,1 himetric=0.01毫米。所以,打印地图时需要将w,h 乘100换算为毫米。
在vb 中例子:
Private Sub Command4_Click()
On Error GoTo ErrorHandler ` Set up error handler.
' coords must be in himetric
' print same size as on screen, in upper left of page
ScaleMode = 6 `set mode to mm
' there is no Printer.StartDoc method, it seems it is done
' implicitly when you use one of the printer.print methods
' so we need to print something before we print our map
' to start the page
Printer.CurrentX = 0
Printer.CurrentY = 0
Printer.Print " "
Map1.PrintMap Printer.hDC, 0, 0, Map1.Width * 100, _
Map1.Height * 100
Printer.NewPage ` Send new page.
Printer.EndDoc ` Printing is finished.
Exit Sub
在vc中例子
// Map.PaperUnit Property
// Map.PrintMap Method
void CSampleProjectView::OnPrintMap(CDC* pDC,CPrintInfo* pInfo) {
try {
// get paper width in mm and convert to HIMETRIC (100th of a mm)
m_Map.SetPaperUnit(miUnitMillimeter);
double pw = m_Map.GetMapPaperWidth() * 100;
double ph = m_Map.GetMapPaperHeight()* 100;
m_Map.PrintMap((long)pDC->m_hDC,
pInfo->m_rectDraw.left,pInfo->m_rectDraw.
top,(long)pw,(long)ph);
} catch (COleDispatchException *e) {
e->ReportError();
e->Delete();
} catch (COleException *e) {
e->ReportError();
e->Delete();
}
}
mapx中创建测距工具示例
首先创建测距工具
global const calculatedistance=1
Private Sub Form_Load()
map1.CreateCustomTool(calcilatedistance,miToolTypepoly ,microsscursor)
End Sub
Private Sub Distances_Click()
map1.currenttool=calculatetool
End Sub
然后在mapx的PolyToolUsed事件中, 用Distance( x1,y1,x2,y2 )计算距离,由状态条中或label显示。
Private Sub Map1_PolyToolUsed(ByVal ToolNum As Integer, ByVal Flags As Long, ByVal points As Object, ByVal bShift As Boolean, ByVal bCtrl As Boolean, EnableDefault As Boolean)
Dim DisSum As Double
Dim Dis As Double
Dim n As Integer
Dim pts As New MapXLib.points
Dim x1 As Double, y1 As Double, x2 As Double, y2 As Double
Set pts = points
DisSum = 0
MDIForm1.StatusBar1.Panels.Item(3).Text= Format(Str(DisSum), "#,##0.000000")
Select Case Flags
Case miPolyToolBegin
Case miPolyToolInProgress
If ToolNum = CalculateDistance Then
For i = 1 To pts.Count - 1
x1 = pts.Item(i).X
y1 = pts.Item(i).Y
x2 = pts.Item(i + 1).X
y3 = pts.Item(i + 1).Y
Dis = Map1.Distance(x1, y1, x2, y2)
DisSum = DisSum + Dis
MDIForm1.StatusBar1.Panels.Item(3).Text = Format(Str(DisSum), "#,##0.000000")
Next i
End If
Case miPolyToolEnd
End Select
在mapx中如何实现自动滚屏
mapx 支持 MouseMove 事件,可以在此事件中实现自动滚屏,示例如下:
Private Sub Map1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If map_move = True Then
If X > Map1.MapScreenWidth - 10 Then
Map1.CenterX = Map1.CenterX + 0.05
Map1.Refresh
Else
If X < 10 Then
Map1.CenterX = Map1.CenterX - 0.05
Map1.Refresh
Else
If Y > Map1.MapScreenHeight - 10 Then
Map1.CenterY = Map1.CenterY - 0.05
Map1.Refresh
Else
If Y < 10 Then
Map1.CenterY = Map1.CenterY + 0.05
Map1.Refresh
End If
End If
End If
End If
End If
End Sub
在mapx中如何实现图元的拖拽
以下方法实现将选中图元移到点击处。
Private Sub Map1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim ftr As Feature
Dim lyr As Layer
Dim MapX As Double
Dim MapY As Double
'convert where the mouse is clicked to the map's current coordinate system
Map1.ConvertCoord X, Y, MapX, MapY, miScreenToMap
'iterate through each selected feature in each layer
For Each lyr In Map1.Layers
For Each ftr In lyr.Selection
'change the offset of the feature
ftr.Offset MapX - ftr.CenterX, MapY - ftr.CenterY
'update the feature to make the change permanent
ftr.Update
Next
Next
End SUb